import 'dart:typed_data';
import 'dart:ui';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

/* 
  使用：
    /// 创建需要截图的Widget
    Widget schoolPinView = createPinWidget(
      '测试',
      subTitle: '学校',
      bgColor: const Color(0xfff56200),
      pinName: 'school_pin',
      width: schoolWidth,
    );
    
    Uint8List? schoolUint8List = await CNMScreenshotUtils.createImageFromWidget(schoolPinView);
 */

/// 针对Widget进行截图
///
/// 小部件 转 Uint8List
///
class CNMScreenshotUtils {
  /// 针对Widget进行截图
  ///
  /// widget：所要截图的小部件
  ///
  static Future<Uint8List?> createImageFromWidget(
    Widget widget, {
    Size? logicalSize,
    Size? imageSize,
  }) async {
    final RenderRepaintBoundary repaintBoundary = RenderRepaintBoundary();
    Iterable<FlutterView> views = WidgetsBinding.instance.platformDispatcher.views;

    if (views.isEmpty) {
      return null;
    }
    final ui.FlutterView dispatcher = views.first;
    final MediaQueryData mediaQueryData = MediaQueryData.fromView(views.first);

    logicalSize ??= dispatcher.physicalSize / mediaQueryData.devicePixelRatio;
    imageSize ??= dispatcher.physicalSize;

    final RenderView renderView = RenderView(
      view: views.first,
      child: RenderPositionedBox(
        alignment: Alignment.center,
        child: repaintBoundary,
      ),
      configuration: ViewConfiguration(
        size: logicalSize,
        devicePixelRatio: 1,
      ),
    );

    final PipelineOwner pipelineOwner = PipelineOwner();
    final BuildOwner buildOwner = BuildOwner(focusManager: FocusManager.instance);

    pipelineOwner.rootNode = renderView;
    renderView.prepareInitialFrame();

    final RenderObjectToWidgetElement<RenderBox> rootElement = RenderObjectToWidgetAdapter<RenderBox>(
      container: repaintBoundary,
      child: widget,
    ).attachToRenderTree(buildOwner);

    buildOwner.buildScope(rootElement);
    buildOwner.finalizeTree();

    pipelineOwner.flushLayout();
    pipelineOwner.flushCompositingBits();
    pipelineOwner.flushPaint();

    final ui.Image image = await repaintBoundary.toImage(pixelRatio: imageSize.width / logicalSize.width);
    final ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png);

    return byteData?.buffer.asUint8List();
  }
}
